package com.kelvin.paopao.easemob;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import com.hyphenate.EMCallBack;
import com.hyphenate.EMConnectionListener;
import com.hyphenate.EMError;
import com.hyphenate.EMGroupChangeListener;
import com.hyphenate.EMMessageListener;
import com.hyphenate.chat.EMClient;
import com.hyphenate.chat.EMCmdMessageBody;
import com.hyphenate.chat.EMMessage;
import com.hyphenate.chat.EMOptions;
import com.hyphenate.chat.EMTextMessageBody;
import com.hyphenate.easeui.controller.EaseUI;
import com.hyphenate.easeui.domain.EaseEmojicon;
import com.hyphenate.easeui.domain.EaseEmojiconGroupEntity;
import com.hyphenate.easeui.domain.EaseUser;
import com.hyphenate.easeui.model.EaseAtMessageHelper;
import com.hyphenate.easeui.model.EaseNotifier;
import com.hyphenate.easeui.utils.EaseCommonUtils;
import com.hyphenate.easeui.utils.SpUtil;
import com.hyphenate.exceptions.HyphenateException;
import com.kelvin.kelvinlib.db.dao.DaoSession;
import com.kelvin.kelvinlib.db.dao.UserInfoDao;
import com.kelvin.kelvinlib.db.table.UserInfo;
import com.kelvin.kelvinlib.utils.LogUtil;
import com.kelvin.paopao.PaoPaoApplication;
import com.kelvin.paopao.api.RetrofitService;
import com.kelvin.paopao.api.responseBean.CommonListResponse;
import com.kelvin.paopao.api.responseBean.UserDetailModel;
import com.kelvin.paopao.module.chat.chat.ChatActivity;
import com.kelvin.paopao.module.main.MainActivity;
import com.kelvin.paopao.R;
import com.kelvin.paopao.rxbus.RxBus;
import com.kelvin.paopao.rxbus.event.ChatEvent;
import com.kelvin.paopao.utils.Constant;
import com.kelvin.paopao.utils.MessageUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;

/**
 * 环信通信云的帮助类
 * <p>
 * 这个类用户初始化环信，注意在需要使用监听的类中注册各类型的监听，
 * 注意给easeui中pushactivity以便提示环信不要用通知提示
 * Created by kelvin on 2016/11/2.
 */

public class EaseMobHelper {

    private EaseUI easeUI;
    //记录是否注册了群组和联系人的监听，防止这个方法被调用两次
    private boolean isGroupAndContactListenerRegisted;

    //正在同步群组数据
    private boolean isSyncingGroupsWithServer;
    //是否同步了群组数据
    private boolean isGroupsSyncedWithServer;

    public static EaseMobHelper instance;
    private Context context;

    private EasemobModel easemobModel;

    //正在视频中的话，打开视频界面
    public boolean isVideoCalling;
    //正在通话中的话，打开通话界面
    public boolean isVoiceCalling;
    //rxbus
    private RxBus rxBus;


    private EaseMobHelper() {

    }

    //记录activity
    public void pushActivity(Activity activity) {
        easeUI.pushActivity(activity);
    }

    public void popActivity(Activity activity) {
        easeUI.popActivity(activity);
    }

    /**
     * 同步回掉
     */
    public interface DataSyncListener {
        /**
         * 同步成功
         *
         * @param success
         */
        void onSyncComplete(boolean success);
    }

    /**
     * 这玩意相当于一个观察者模式，也可以用eventbus实现 这个项目两种方法都使用
     */
    private List<DataSyncListener> syncGroupsListeners;

    public static EaseMobHelper getInstance() {
        if (instance == null) {
            synchronized (EaseMobHelper.class) {
                if (instance == null) {
                    instance = new EaseMobHelper();
                }
            }
        }
        return instance;
    }

    /**
     * 初始化环信的所有配置的方法
     *
     * @param context
     */
    public void init(Context context, RxBus rxBus) {

        this.rxBus = rxBus;

        easemobModel = new EasemobModel(context);
        EMOptions options = new EMOptions();
        // 默认添加好友时，是不需要验证的，改成需要验证
        options.setAcceptInvitationAlways(false);
        // 已读确认
        options.setRequireAck(true);
        // 送达确认
        options.setRequireDeliveryAck(false);
        //gcm推送
//        options.setGCMNumber("324169311137");
        //小米手机上可以使用小米推送
//        options.setMipushConfig("2882303761517426801", "5381742660801");
        //华为手机上可以使用华为推送
//        options.setHuaweiPushAppId("10492024");

        //设置是否允许聊天室群主离开
        options.allowChatroomOwnerLeave(getModel().isChatroomOwnerLeaveAllowed());
        //设置退出群组时删除聊天数据
        options.setDeleteMessagesAsExitGroup(getModel().isDeleteMessagesAsExitGroup());
        //是个自动同意加群申请
        options.setAutoAcceptGroupInvitation(getModel().isAutoAcceptGroupInvitation());
        if (EaseUI.getInstance().init(context, options)) {
            this.context = context;
            //在做打包混淆时，关闭debug模式，避免消耗不必要的资源
            EMClient.getInstance().setDebugMode(true);
            easeUI = EaseUI.getInstance();
            //设置easesui的样式和配置
            setEaseUIProviders();

            setGlobalListeners();
        }
    }

    private void setEaseUIProviders() {
        //需要EaseUI库显示用户头像和昵称设置此provider
        easeUI.setUserProfileProvider(new EaseUI.EaseUserProfileProvider() {

            @Override
            public EaseUser getUser(String username) {
                return getUserInfo(username);
            }
        });

//        设置声音振动等提示的提供者（不设置则使用 EaseUI 默认的）
        easeUI.setSettingsProvider(new EaseUI.EaseSettingsProvider() {

            @Override
            public boolean isSpeakerOpened() {
                return easemobModel.getSettingMsgSpeaker();
            }

            @Override
            public boolean isMsgVibrateAllowed(EMMessage message) {
                return easemobModel.getSettingMsgVibrate();
            }

            @Override
            public boolean isMsgSoundAllowed(EMMessage message) {
                return easemobModel.getSettingMsgSound();
            }

            @Override
            public boolean isMsgNotifyAllowed(EMMessage message) {
                if (message == null) {
                    return easemobModel.getSettingMsgNotification();
                }
                if (!easemobModel.getSettingMsgNotification()) {
                    return false;
                } else {
                    String chatUsename = null;
                    List<String> notNotifyIds = null;
                    //不显示通知的人员和群组名单
                    // get user or group id which was blocked to show message notifications
                    if (message.getChatType() == EMMessage.ChatType.Chat) {
                        chatUsename = message.getFrom();
                        notNotifyIds = easemobModel.getDisabledIds();
                    } else {
                        chatUsename = message.getTo();
                        notNotifyIds = easemobModel.getDisabledGroups();
                    }

                    if (notNotifyIds == null || !notNotifyIds.contains(chatUsename)) {
                        return true;
                    } else {
                        return false;
                    }
                }
            }
        });
        //设置表情provider
        easeUI.setEmojiconInfoProvider(new EaseUI.EaseEmojiconInfoProvider() {

            @Override
            public EaseEmojicon getEmojiconInfo(String emojiconIdentityCode) {
                EaseEmojiconGroupEntity data = EmojiconExampleGroupData.getData();
                for (EaseEmojicon emojicon : data.getEmojiconList()) {
                    if (emojicon.getIdentityCode().equals(emojiconIdentityCode)) {
                        return emojicon;
                    }
                }
                return null;
            }

            @Override
            public Map<String, Object> getTextEmojiconMapping() {
                return null;
            }
        });

//        设置通知栏内容提供者（不设置则使用默认的）
        easeUI.getNotifier().setNotificationInfoProvider(new EaseNotifier.EaseNotificationInfoProvider() {

            @Override
            public String getTitle(EMMessage message) {

                return null;
            }

            //TODO 这里需要修改通知的icon
            @Override
            public int getSmallIcon(EMMessage message) {
                return R.mipmap.ic_launcher;
            }

            @Override
            public String getDisplayedText(EMMessage message) {
                // 设置状态栏的消息提示，可以根据message的类型做相应提示
                String ticker = EaseCommonUtils.getMessageDigest(message, context);
                if (message.getType() == EMMessage.Type.TXT) {
                    ticker = ticker.replaceAll("\\[.{2,3}\\]", "[表情]");
                }
                EaseUser user = getUserInfo(message.getFrom());
                if (user != null) {
                    //如果是at我的（在群组里）
                    if (EaseAtMessageHelper.get().isAtMeMsg(message)) {
                        return String.format(context.getString(R.string.at_your_in_group), user.getNick());
                    }
                    String username = "";
                    if (message.getChatType() == EMMessage.ChatType.Chat) {
                        //如果是单聊
                        try {
                            username = message.getStringAttribute("EASE_Nik_Name");
                        } catch (HyphenateException e) {
                            e.printStackTrace();
                            username = message.getFrom();
                        }
                    } else if (message.getChatType() == EMMessage.ChatType.GroupChat) {
                        try {
                            username = message.getStringAttribute("EASE_Nik_Name");
                        } catch (HyphenateException e) {
                            e.printStackTrace();
                            username = message.getFrom();
                        }
                    }
                    return username + ": " + ticker;
                } else {
                    if (EaseAtMessageHelper.get().isAtMeMsg(message)) {
                        return String.format(context.getString(R.string.at_your_in_group), message.getFrom());
                    }

                    return message.getFrom() + ": " + ticker;
                }
            }

            @Override
            public String getLatestText(EMMessage message, int fromUsersNum, int messageNum) {
                // 自定义消息通知的文字
                String text = generateNotifitext(message);
                return text;
            }

            @Override
            public Intent getLaunchIntent(EMMessage message) {
                //设置点击通知栏跳转事件
                Intent intent = new Intent(context, ChatActivity.class);
                // open calling activity if there is call
                if (isVideoCalling) {
                } else if (isVoiceCalling) {
                } else {

                    EMMessage.ChatType chatType = message.getChatType();
                    if (chatType == EMMessage.ChatType.Chat) { // 如果是单聊
                        intent.putExtra("userId", message.getFrom());
                        intent.putExtra("chatType", Constant.CHATTYPE_SINGLE);
                    } else { //如果是群聊
                        // message.getTo()获得群组id
                        intent.putExtra("userId", message.getTo());
                        if (chatType == EMMessage.ChatType.GroupChat) {
                            intent.putExtra("chatType", Constant.CHATTYPE_GROUP);
                        } else {
                            intent.putExtra("chatType", Constant.CHATTYPE_CHATROOM);
                        }

                    }
                }
                return intent;
            }
        });
    }

    /**
     * 生成通知文字
     *
     * @param message
     */
    private String generateNotifitext(EMMessage message) {
        String content = EaseCommonUtils.getMessageDigest(message, (this.context));
        String user = null;
        if (message.getChatType() == EMMessage.ChatType.Chat) {
            //单聊
            user = message.getStringAttribute("EASE_Nik_Name", "");
            if (message.getBooleanAttribute("Ease_Message_Type_Key", false)) {
                //如果是关注信息(文字)
                return ((EMTextMessageBody) message.getBody()).getMessage();
            }
        } else if (message.getChatType() == EMMessage.ChatType.GroupChat) {
            //群聊
            user = message.getStringAttribute("EASE_Nicname_Group_Key", "");
        }
        String text = user + ":" + content;
        return text;
    }

    //TODO
    //获取用户信息
    private EaseUser getUserInfo(String username) {
        EaseUser user = null;
        //获取当前登录用户的用户名
        if (username.equals(EMClient.getInstance().getCurrentUser())) {


            return user;
        }

        //然后从通讯录中查找用户
        //TODO 从通讯录中查找
//        user = getContactList().get(username);

        //TODO 这里可以做得更加人性化
        // 如果都没有的给一个首字母它，这种情况是未知用户得到当前用户的环信id发的东西
        if (user == null) {
            user = new EaseUser(username);
            EaseCommonUtils.setUserInitialLetter(user);
        }
        return user;
    }


    EMConnectionListener connectionListener;

    private void setGlobalListeners() {
        syncGroupsListeners = new ArrayList<DataSyncListener>();

        isGroupsSyncedWithServer = easemobModel.isGroupsSynced();


        //监听链接状态
        connectionListener = new EMConnectionListener() {
            @Override
            public void onDisconnected(int error) {
                LogUtil.d("onDisconnect" + error);
                if (error == EMError.USER_REMOVED) {
                    //用户被删除
                    onUserException(Constant.ACCOUNT_REMOVED);
                } else if (error == EMError.USER_LOGIN_ANOTHER_DEVICE) {
                    //用户在别处登陆
                    onUserException(Constant.ACCOUNT_CONFLICT);
                } else if (error == EMError.SERVER_SERVICE_RESTRICTED) {
                    //用户被禁用
                    onUserException(Constant.ACCOUNT_FORBIDDEN);
                }
            }

            @Override
            public void onConnected() {
                //如果已经同步过群组和联系人数据的话就不用
                if (isGroupsSyncedWithServer) {
                    LogUtil.d("group  already synced with servre");
                } else {
                    if (!isGroupsSyncedWithServer) {
                        asyncFetchGroupsFromServer(null);
                    }
                }
            }
        };


        //注册链接状态监听
        EMClient.getInstance().addConnectionListener(connectionListener);
        //注册群组和联系人监听
        registerGroupAndContactListener();
        //注册消息监听
        registerMessageListener();
    }

    public void noitifyGroupSyncListeners(boolean success) {
        for (DataSyncListener listener : syncGroupsListeners) {
            listener.onSyncComplete(success);
        }
    }

    private void asyncFetchGroupsFromServer(final EMCallBack callback) {
        if (isSyncingGroupsWithServer) {
            return;
        }
        isSyncingGroupsWithServer = true;

        new Thread() {
            @Override
            public void run() {
                try {
                    //先加载服务器的群组
                    EMClient.getInstance().groupManager().getJoinedGroupsFromServer();

                    // in case that logout already before server returns, we should return immediately
                    if (!isLoggedIn()) {
                        isGroupsSyncedWithServer = false;
                        isSyncingGroupsWithServer = false;
                        noitifyGroupSyncListeners(false);
                        return;
                    }

                    easemobModel.setGroupsSynced(true);

                    isGroupsSyncedWithServer = true;
                    isSyncingGroupsWithServer = false;

                    //TODO 同步群组数据成功
                    noitifyGroupSyncListeners(true);

                    if (callback != null) {
                        callback.onSuccess();
                    }
                } catch (HyphenateException e) {
                    easemobModel.setGroupsSynced(false);
                    isGroupsSyncedWithServer = false;
                    isSyncingGroupsWithServer = false;
                    noitifyGroupSyncListeners(false);
                    if (callback != null) {
                        callback.onError(e.getErrorCode(), e.toString());
                    }
                }

            }
        }.start();
    }

    private void registerGroupAndContactListener() {
        if (!isGroupAndContactListenerRegisted) {
            EMClient.getInstance().groupManager().addGroupChangeListener(new MyGroupChangeListener());
            isGroupAndContactListenerRegisted = true;
        }
    }

    /**
     * 消息监听
     */
    protected EMMessageListener messageListener;

    private void registerMessageListener() {
        messageListener = new EMMessageListener() {
            private BroadcastReceiver broadCastReceiver = null;

            @Override
            public void onMessageReceived(List<EMMessage> messages) {
                for (EMMessage message : messages) {
                    LogUtil.d("onMessageReceived id : " + message.getMsgId());
                    // 前台都没有可以展示消息的activity就用通知的形式通知用户
                    //这里需要注意给这个前台activity集合中添加可以展示消息的activity

                    if (message.getChatType() == EMMessage.ChatType.Chat) {
                        rxBus.send(new ChatEvent(ChatEvent.SINGLE_CHAT));
                    } else if (message.getChatType() == EMMessage.ChatType.GroupChat) {
                        rxBus.send(new ChatEvent(ChatEvent.GROUP_CHAT));
                    } else {
                        rxBus.send(new ChatEvent(ChatEvent.CHAT_ROOM));
                    }

                    if (!easeUI.hasForegroundActivies()) {
                        LogUtil.d("onnewmsgcome:notify");

                        easeUI.getNotifier().onNewMsg(message);
                    }
                    final String user_no = message.getFrom();
                    DaoSession daoSession = ((PaoPaoApplication) context.getApplicationContext()).getDaoSession();
                    final UserInfoDao dao = daoSession.getUserInfoDao();

                    //数据库如果不存在这个用户
                    try {
                        String avatar = message.getStringAttribute("EASE_Avatar");
                        String nickname = message.getStringAttribute("EASE_Nik_Name");
                        LogUtil.d("avatar:" + avatar + ",nickname:" + nickname);
                        UserInfo userInfo = new UserInfo(Long.parseLong(user_no), nickname, avatar, null);
                        dao.insert(userInfo);
                    } catch (HyphenateException e) {
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void onCmdMessageReceived(List<EMMessage> messages) {
                for (EMMessage message : messages) {
                    String action = ((EMCmdMessageBody) message.getBody()).action();
                    LogUtil.d("receive command message:" + action);
                    //不使用透传消息功能就可以不使用这个方法
                    MessageUtil.dealMessageBean(action, context);
                }
            }

            @Override
            public void onMessageRead(List<EMMessage> list) {

            }

            @Override
            public void onMessageDelivered(List<EMMessage> list) {

            }

            @Override
            public void onMessageChanged(EMMessage message, Object change) {

            }
        };

        EMClient.getInstance().chatManager().addMessageListener(messageListener);
    }

    /**
     * 登陆
     *
     * @param userNumber 在环信中的idd
     */
    public void login(String userNumber, final EMCallBack callBack) {
        LogUtil.d("userName:" + userNumber);
        EMClient.getInstance().login(userNumber, "123456", new EMCallBack() {//回调
            @Override
            public void onSuccess() {
                if (callBack != null) {
                    callBack.onSuccess();
                }
            }

            @Override
            public void onProgress(int progress, String status) {
                if (callBack != null) {
                    callBack.onProgress(progress, status);
                }
            }

            @Override
            public void onError(int code, String message) {
                if (callBack != null) {
                    callBack.onError(code, message);
                }
            }
        });
    }

    /**
     * sdk默认是自动登陆的所以在展示主界面调用这个方法，后面好拿出会话记录和群组记录
     *
     * @return
     */
    public boolean isLoggedIn() {
        return EMClient.getInstance().isLoggedInBefore();
    }

    /**
     * 退出登录的方法
     *
     * @param unbindDeviceToken 是否解绑，是的话退出后不会收到信息，也可能出现网络问题，就算是true也能接受到信息
     * @param callback          暴露出去的回调
     */
    public void logout(boolean unbindDeviceToken, final EMCallBack callback) {
        //如果有呼叫的话，先要endcall
        EMClient.getInstance().logout(unbindDeviceToken, new EMCallBack() {

            @Override
            public void onSuccess() {
                reset();
                if (callback != null) {
                    callback.onSuccess();
                }
            }

            @Override
            public void onProgress(int progress, String status) {
                if (callback != null) {
                    callback.onProgress(progress, status);
                }
            }

            @Override
            public void onError(int code, String error) {
                reset();
                if (callback != null) {
                    callback.onError(code, error);
                }
            }
        });
    }


    synchronized void reset() {
        isSyncingGroupsWithServer = false;
        easemobModel.setGroupsSynced(false);
        isGroupsSyncedWithServer = false;
        isGroupAndContactListenerRegisted = false;
    }

    /**
     * group change listener
     */
    class MyGroupChangeListener implements EMGroupChangeListener {

        @Override
        public void onInvitationReceived(String s, String s1, String s2, String s3) {

        }

        @Override
        public void onRequestToJoinReceived(String s, String s1, String s2, String s3) {

        }

        @Override
        public void onRequestToJoinAccepted(String s, String s1, String s2) {

        }

        @Override
        public void onRequestToJoinDeclined(String s, String s1, String s2, String s3) {

        }

        @Override
        public void onInvitationAccepted(String s, String s1, String s2) {

        }

        @Override
        public void onInvitationDeclined(String s, String s1, String s2) {

        }

        @Override
        public void onUserRemoved(String s, String s1) {

        }

        @Override
        public void onGroupDestroyed(String s, String s1) {

        }

        @Override
        public void onAutoAcceptInvitationFromGroup(String s, String s1, String s2) {

        }

        @Override
        public void onMuteListAdded(String s, List<String> list, long l) {

        }

        @Override
        public void onMuteListRemoved(String s, List<String> list) {

        }

        @Override
        public void onAdminAdded(String s, String s1) {

        }

        @Override
        public void onAdminRemoved(String s, String s1) {

        }

        @Override
        public void onOwnerChanged(String s, String s1, String s2) {

        }

        @Override
        public void onMemberJoined(String s, String s1) {

        }

        @Override
        public void onMemberExited(String s, String s1) {

        }
    }

    /**
     * 账号出现异常时候的处理方法
     */
    protected void onUserException(String exception) {
        LogUtil.d("onUserException: " + exception);
        Intent intent = new Intent(context, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(exception, true);
        context.startActivity(intent);
    }

    public EasemobModel getModel() {
        return easemobModel;
    }

    /**
     * 封装的通知
     */
    private EaseNotifier notifier;

    public EaseNotifier getNotifier() {
        return easeUI.getNotifier();
    }

    public void addSyncGroupListener(DataSyncListener listener) {
        if (listener == null) {
            return;
        }
        if (!syncGroupsListeners.contains(listener)) {
            syncGroupsListeners.add(listener);
        }
    }

    public void removeSyncGroupListener(DataSyncListener listener) {
        if (listener == null) {
            return;
        }
        if (syncGroupsListeners.contains(listener)) {
            syncGroupsListeners.remove(listener);
        }
    }
}
